{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "ebeec468",
   "metadata": {},
   "source": [
    "面向对象最终要的概念就是类class和实例instance，必须牢记类是抽象的模板，比如student类       "
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9c32495f",
   "metadata": {},
   "source": [
    "实例时根据类创建出来的一个个具体的对象，每个对象都有 相同的方法，但各自的数据可能不同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "9d6644c5",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(object): #class后面接的是类名，(object)表示该类从哪个类继承下来，如果没有合适的继承类，就使用object类。\n",
    "    pass"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "94dd19e6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<__main__.Student at 0x26a6ee37e50>"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bart = Student()\n",
    "bart #可以看出bart指向一个student实例，后面跟着的是内存地址"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "94f65e69",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "__main__.Student"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "Student #本身是一个类"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "d366afb6",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Bart test'"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bart.name = 'Bart test' #可以自由给一个实例绑定属性\n",
    "bart.name"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e9efaa2",
   "metadata": {},
   "source": [
    "类可以起到模板的作用，因此在创建类的时候，把一些我们认为必须绑定的属性强制填写进去。"
   ]
  },
  {
   "cell_type": "raw",
   "id": "a1d0959b",
   "metadata": {},
   "source": [
    "通过定义一个特殊的__init__方法，就把name，score等属性绑上去。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "28b4a5c2",
   "metadata": {},
   "outputs": [],
   "source": [
    "class Student(object):\n",
    "    def __init__(self,name,score):\n",
    "        self.name = name\n",
    "        self.score = score"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f4c9a19f",
   "metadata": {},
   "source": [
    "init第一个参数永远是self，表示创建的实例本身，在init方法内部，就可以把各种属性绑定到self，因为self指向创建的实例本身"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c81ae332",
   "metadata": {},
   "source": [
    "有了init方法，在创建实例的时候，就不能 传入空的参数了，必须传入与init方法匹配的参数，\n",
    "但self不需要传，Python解释器自己会把实例变量传进去"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "a9bfc079",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "'Bart'"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bart = Student('Bart', 59)\n",
    "bart.name"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "3a103f5f",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "59"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "bart.score"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "fb596158",
   "metadata": {},
   "source": [
    "和普通的函数相比，在类中定义的函数只有一点不同，就是第一个参数永远是实例变量self，并且\n",
    "调用时不用传入该参数，其他没有区别。"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "66209fd9",
   "metadata": {},
   "source": [
    "### 数据封装"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "93491c38",
   "metadata": {},
   "source": [
    "可以直接在Student类的内部定义访问数据的函数，这样就把数据封装起来了，这些封装数据的函数和Student类本身关联起来"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ffde2251",
   "metadata": {},
   "source": [
    "我们称之为类的方法："
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "d98c6da6",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Bart:59\n"
     ]
    }
   ],
   "source": [
    "class Student(object):\n",
    "    def __init__(self, name, score):\n",
    "        self.name = name\n",
    "        self.score = score\n",
    "    def print_score(self):\n",
    "        print(\"%s:%s\" % (self.name, self.score))\n",
    "bart = Student('Bart', 59)\n",
    "bart.print_score()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "f63de0f7",
   "metadata": {},
   "source": [
    "这样来看，我们从外部看student类，就只需要直到，创建实例需要给出name和score，而如何打印，都是在Student类的内部定义的"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "67bcb75e",
   "metadata": {},
   "source": [
    "封装的另一个号出是可以给Student类增加新的方法，比如get_grade"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "a39ca80f",
   "metadata": {},
   "source": [
    "### 小结"
   ]
  },
  {
   "cell_type": "raw",
   "id": "b4810ecc",
   "metadata": {},
   "source": [
    "类是创建实例的模板，而实例则是一个一个具体的对象，各个实例拥有的数据都互相独立\n",
    "方法就是与实例绑定的函数，方法可以直接访问实例的数据\n",
    "通过在实力上调用方法，我们直接操作对象内部的数据，无需直到方法内部实现细节\n",
    "Python允许对实例变量绑定任何数据，即动态绑定新的属性。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "89cda7f1",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
